﻿using System;
using Firefly.Framework.Graphics;
using Firefly.Framework.Input;
using Firefly.Framework.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace Firefly.Framework.Windows
{
    public class Theme : IHasContent, IDisposableEx
    {
        public CursorCollection Cursors { get; set; }
        public FontCollection Fonts { get; set; }
        public StretchThemePart Form { get; set; }
        public StretchThemePart Button { get; set; }
        public StretchThemePart Textbox { get; set; }
        public ThemePart Toggle { get; set; }
        public ThemePart Scrollbar { get; set; }
        [ContentSerializerIgnore]
        public Texture2D Pixel { get; set; }
        [ContentSerializer(Optional = true)]
        public Color CursorColor { get; set; }

        public Theme()
        {
            Cursors = new CursorCollection();
            Fonts = new FontCollection();
            CursorColor = Color.White;
        }

        public void DrawCursor(GameTime gameTime)
        {
            Control control = WindowsService.Instance.FindComponent(InputService.Instance.MouseManager.CurrentAxisPosition);
            string cursor = (control != null) ? control.Cursor : "Default";
            Cursors[cursor].Draw(gameTime);
        }

        private Texture2D CreatePixelTexture(int width, int height, Color color)
        {
            RenderTarget2D LevelRenderTarget = new RenderTarget2D(GraphicsService.Instance.GraphicsDevice, 
                width, 
                height, 
                1,
                GraphicsService.Instance.GraphicsDevice.PresentationParameters.BackBufferFormat,
                GraphicsService.Instance.GraphicsDevice.PresentationParameters.MultiSampleType,
                GraphicsService.Instance.GraphicsDevice.PresentationParameters.MultiSampleQuality, 
                RenderTargetUsage.PreserveContents);
            DepthStencilBuffer stencilBuffer = new DepthStencilBuffer(GraphicsService.Instance.GraphicsDevice, 
                width, 
                height,
                GraphicsService.Instance.GraphicsDevice.DepthStencilBuffer.Format,
                GraphicsService.Instance.GraphicsDevice.PresentationParameters.MultiSampleType,
                GraphicsService.Instance.GraphicsDevice.PresentationParameters.MultiSampleQuality);
            GraphicsService.Instance.GraphicsDevice.SetRenderTarget(0, LevelRenderTarget);
            DepthStencilBuffer oldStencilBuffer = GraphicsService.Instance.GraphicsDevice.DepthStencilBuffer;
            GraphicsService.Instance.GraphicsDevice.DepthStencilBuffer = stencilBuffer;
            GraphicsService.Instance.GraphicsDevice.Clear(color);
            GraphicsService.Instance.GraphicsDevice.SetRenderTarget(0, null);
            GraphicsService.Instance.GraphicsDevice.DepthStencilBuffer = oldStencilBuffer;
            return LevelRenderTarget.GetTexture();
        }

        private void DeviceReset(object sender, EventArgs e)
        {
            Pixel = CreatePixelTexture(1, 1, Color.White);
        }

        #region IPipelineSerializable Members

        public void DeserializeContent(ContentReader input)
        {
            Cursors = input.ReadObject<CursorCollection>();

            if (!Cursors.ContainsKey("Default"))
            {
                throw new ApplicationException("A cursor named 'Default' must be defined.");
            }

            Fonts = input.ReadObject<FontCollection>();
            Form = input.ReadObject<StretchThemePart>();
            Button = input.ReadObject<StretchThemePart>();
            Textbox = input.ReadObject<StretchThemePart>();
            Toggle = input.ReadObject<ThemePart>();
            Scrollbar = input.ReadObject<ThemePart>();
        }

        #endregion

        #region IHasContent Members

        public void LoadContent()
        {
            GraphicsService.Instance.GraphicsDevice.DeviceReset += new EventHandler(DeviceReset);
            Pixel = CreatePixelTexture(1, 1, Color.White);
        }

        public void UnloadContent()
        {
            Pixel.Dispose();

            foreach (string c in Cursors.Keys)
            {
                Cursors[c].Dispose();
            }

            foreach (string f in Fonts.Keys)
            {
                Fonts[f].Dispose();
            }

            Form.Dispose();
            Button.Dispose();
            Textbox.Dispose();
            Toggle.Dispose();
            Scrollbar.Dispose();
        }

        #endregion

        #region IDisposableEx Members

        public bool Disposed { get; private set; }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (!Disposed)
            {
                if (disposing)
                {
                    UnloadContent();
                }

                Disposed = true;
            }
        }

        ~Theme()
        {
            Dispose(false);
        }

        #endregion
    }
}
